package com.tianji.learning.service.impl;

import com.tianji.api.client.course.CourseClient;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.leanring.LearningLessonDTO;
import com.tianji.api.dto.leanring.LearningRecordDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningRecordFormDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.enums.SectionType;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.util.LearningRecordDelayTaskHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.jar.JarEntry;

/**
 * <p>
 * 学习记录表 服务实现类
 * </p>
 *
 * @author mytjxt
 * @since 2024-05-23
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class LearningRecordServiceImpl extends ServiceImpl<LearningRecordMapper, LearningRecord> implements ILearningRecordService {

final LearningLessonServiceImpl learningLessonService;
final CourseClient courseClient;
final LearningRecordDelayTaskHandler learningRecordDelayTaskHandler;
    @Override
    public LearningLessonDTO queryLearningRecordByCourse(Long courseId) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        // 2.查询课表-得到课表id和最近学习小节id
        LearningLesson learningLesson = learningLessonService.lambdaQuery()
                .eq(LearningLesson::getUserId, userId)
                .eq(LearningLesson::getCourseId, courseId).one();
        if (learningLesson == null) {
            throw new BizIllegalException("该课程未加入课表");
        }
        Long lessonId = learningLesson.getId();
        //3.查询学习记录
        List<LearningRecord> list = lambdaQuery()
                .eq(LearningRecord::getLessonId, lessonId).list();

        LearningLessonDTO dto = new LearningLessonDTO();
        dto.setId(lessonId);
        dto.setLatestSectionId(learningLesson.getLatestSectionId());
        dto.setRecords(BeanUtils.copyList(list, LearningRecordDTO.class));


        return dto;
    }


    @Override
    public void addLearningRecord(LearningRecordFormDTO recordDTO) {
        // 1.获取当前登录用户
        Long userId = UserContext.getUser();
        //2.处理学习记录
        boolean isfinished = false;//是否是第一次完成
        //2.1是否考试-是，提交考试记录

        if (recordDTO.getSectionType()== SectionType.EXAM){
            isfinished   = handleExamRecord(recordDTO, userId);

        }else {
            // 2.1.处理视频
            isfinished = handleVideoRecord( recordDTO,userId);
            }

        //3.课表更新
        if (!isfinished){
        return;
        }

        handleLearningLessonsChanges(recordDTO);

    }

    private void handleLearningLessonsChanges(LearningRecordFormDTO recordDTO) {
        // 1.查询课表
        LearningLesson lesson = learningLessonService.getById(recordDTO.getLessonId());
        if (lesson == null) {
            throw new BizIllegalException("课程不存在，无法更新数据！");
        }
        //2.判断是否第一次完成

        //是第一次学完
        //2.1小节数+1
        //2.2  判断课程是否全部学完 比较已经学完的小节数和总小节数
        boolean flag = false;

            CourseFullInfoDTO courseInfoById =
                    courseClient.getCourseInfoById(lesson.getCourseId(), true, false);
            Integer totalSection = courseInfoById.getSectionNum();
            Integer isFinishedSection = lesson.getLearnedSections();
            flag= totalSection.equals(isFinishedSection+1);//课程是否全部学完
            //修改课表状态为2 当flag为true，则修改状态为2-已学完，否则为1-学习中
            //特殊情况：课程还没有开始学习，需要设置状态为1-学习中，当课程状态为0-未学习，则修改状态为1-学习中

        //不是第一次学完-更新课表--jia
        learningLessonService.lambdaUpdate()
                .eq(LearningLesson::getId,lesson.getId())
                .set(lesson.getStatus().getValue()==0,LearningLesson::getStatus,1)
                .set(LearningLesson::getLearnedSections,lesson.getLearnedSections()+1)
                .set(flag,LearningLesson::getStatus,2)
                .set(LearningLesson::getLatestLearnTime,recordDTO.getCommitTime())
                .set(LearningLesson::getLatestSectionId,recordDTO.getSectionId())
                .update();


    }

    private boolean handleVideoRecord(LearningRecordFormDTO recordDTO, Long userId) {
        // 1.查询缓存
        LearningRecord cache= queryCach(recordDTO);



        // 2.判断数据库是否存在
        if (cache == null) {
            // 3.不存在，则新增学习记录
            // 3.1.转换PO
            LearningRecord record = BeanUtils.copyBean(recordDTO, LearningRecord.class);
            // 3.2.填充数据
            record.setUserId(userId);
            // 3.3.写入数据库
            boolean success = save(record);
            if (!success) {
                throw new DbException("新增学习记录失败！");
            }
            return false;
        }

        //老数据存在，则更新学习记录--更新三个字段（是否完成，完成时间，当前视频在多少秒）
        //判断是否是完成了50%且是不是已经完成过一次
        boolean finished = recordDTO.getMoment() * 1.0 / recordDTO.getDuration() >= 0.5 && !cache.getFinished();
        //3.是第一次学完
        if (finished){
            //更新数据库--更新学习记录
            boolean update = lambdaUpdate()
                    .eq(LearningRecord::getId, cache.getId())
                    .set(LearningRecord::getMoment, recordDTO.getMoment())//必须更新的字段
                    .set(LearningRecord::getFinished, true)
                    .set(LearningRecord::getFinishTime, recordDTO.getCommitTime())
                    .update();
            if (!update){
                throw new DbException("更新学习记录失败！");
            }
            //删除缓存
        learningRecordDelayTaskHandler.cleanRecordCache(recordDTO.getLessonId(), recordDTO.getSectionId());
            return true;
        }
        //4.不是第一次学完--开启异步延迟任务
       //准备 写入缓存需要的数据
        LearningRecord recordCache    = new LearningRecord();
        recordCache.setLessonId(recordDTO.getLessonId());
        recordCache.setId(cache.getId());
        recordCache.setMoment(recordDTO.getMoment());
        recordCache.setSectionId(recordDTO.getSectionId());
        recordCache.setFinished(cache.getFinished());
        learningRecordDelayTaskHandler.addLearningRecordTask(recordCache);
        return false;

    }

    private LearningRecord queryCach(LearningRecordFormDTO recordDTO) {

        LearningRecord cache =
                learningRecordDelayTaskHandler
                        .readRecordCache(recordDTO.getLessonId(), recordDTO.getSectionId());

        //1.1判断缓存是否存在
        if (cache == null){//数据库不存在，返回null-创建学习计划
            //缓存不存在-查数据库 --查询旧的学习记录
            LearningRecord old = lambdaQuery()
                    .eq(LearningRecord::getLessonId, recordDTO.getLessonId())
                    .eq(LearningRecord::getSectionId, recordDTO.getSectionId())
                    .one();
        if (old==null){
            return null;
        }
            //如果数据库存在--把老数据写入缓存
            learningRecordDelayTaskHandler.writeRecordCache(old);
        return old;
        }

        return cache;



    }

    private boolean handleExamRecord(LearningRecordFormDTO formDTO, Long userId) {

        LearningRecord learningRecord = BeanUtils.copyBean(formDTO, LearningRecord.class);
        learningRecord.setUserId(userId);
        learningRecord.setFinished(true);
        learningRecord.setFinishTime(formDTO.getCommitTime());
        boolean success = save(learningRecord);
        if (!success) {
            throw new DbException("新增考试记录失败！");
        }
       return true;
    }
}
